package com.baizhi.aspect;


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 *
 * @Aspect  标记当前类为切面类
 *
 */


@Configuration
@Aspect
public class RedisAspect {

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 添加缓存
     *
     * 在增强中 需要添加缓存  意味着需要获取方法查询的结果  环绕增强
     *
     * key  类名  getThis
     *
     * hashKey  方法名+参数
     *
     * 1.获取key  和  hashKey
     * 2.根据key和hashKey  看看redis中有没有数据
     * 4.如果没有  方法放行   查询数据库 将数据库的结果 存储在缓存中  并返回
     *
     */
    @Around("@annotation(com.baizhi.annotation.AddCacheAnnotation)")
    public Object  addCache(ProceedingJoinPoint joinPoint) throws Throwable {
//        1.获取key 和 hashKey

        String key = joinPoint.getThis().toString();
        System.out.println("获取key:"+key);

        StringBuffer stringBuffer = new StringBuffer();
//        获取方法名
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String methodName = signature.getMethod().getName();
        stringBuffer.append(methodName);


//        2.获取方法的形参
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            stringBuffer.append(arg.toString());
        }
        String  hashKey=stringBuffer.toString();

        System.out.println("获取hashKey:"+hashKey);

        HashOperations opsForHash = redisTemplate.opsForHash();


        Object result = opsForHash.get(key, hashKey);

        if (result==null){
            result = joinPoint.proceed();
//            将数据库的结果 存储在缓存中
            Map map = new HashMap();
            map.put(hashKey,result);

            opsForHash.putAll(key,map);
            System.out.println("获取数据库数据 添加缓存");

//            添加 缓存自动删除  认为缓存长期来看都是不安全的  即便是不手动删除
//            也需要让redis定期自动删除
            /**
             * expire 设置定期自动删除  设置缓存的存活时间
             *
             * 参数1  要设置的key
             * 参数2 时间
             * 参数3 时间的单位
             */
            redisTemplate.expire(key,10, TimeUnit.SECONDS);

            return result;

        }else {

            System.out.println("从缓存中获取数据");
            return result;

        }

    }

    /**
     * 删除缓存  根据key删除  key是当前类的类名
     * 在增删改之前删除  前置增强
     *
     */
    @Before("@annotation(com.baizhi.annotation.DeleteCacheAnnotation)")
    public void deleteCache(JoinPoint joinPoint){
//        1.获取当前类的类名
        String className = joinPoint.getThis().toString();

//        2.通过类名删除

        redisTemplate.delete(className);




    }

}
